package com.kotlin.lib

class Star<out T> constructor(val value: T)

class Star2<in T> /*constructor(val value: T)*/ {
    //   lateinit var value: T
    fun setValue(t: T) {
//        this.value = t
    }
}

class Star3<T> constructor(val value: T)

fun main() {
    /**
     * 对于Star<out T>协变：如果T的上界是TUpper，那么Star<*>就相当于Star<out T>，
     * 这表示当T的类型未知时，你可以安全地读取TUpper类型的值，
     * 言外之意就是从Star<*>取出来的元素都会当成TUpper类型。
     */
    var star1: Star<Fruit> = Star(Apple())
    var star2: Star<*> = star1
    val value: Any? = star2.value//注意value的类型。
    println("$value ${star1.value} ${value is Apple}")

    /**
     * 对于Star<in T>逆变：Star<*>就相当于Star<in Nothing>.丧失了写的能力
     */
    val star3: Star2<Int> = Star2<Number>()
    val star4: Star2<*> = star3
//    star4.setValue(3)// compile error.

    /**
     * 对于Star<T>不变：如果T的上界为TUpper，那么Star<*>就相当于读取时的Star<out TUpper>以及写入时的Star<in Nothing>
     */
    val star5: Star3<Number> = Star3(5)
    val star6: Star3<*> = star5
    val value1: Any? = star6.value//注意value1的类型。


    val storage: MyStorage<Int> = MyStorage(5)

    val storage2: MyStorage<Any> = storage
    storage2.setValue("hello")
    println(storage2.getValue())

//    val upperBoundsClass = UpperBoundsClass< ArrayList<String>>()

}

class MyStorage<out T> constructor(private var value: T) {
    fun getValue(): T = this.value

    fun setValue(t: @UnsafeVariance T) {
        this.value = t
    }
}

//单个上界限定
class UpperBoundsClass<T : ArrayList<T>>

//多个上界限定
class UpperBoundsClazz<T> where T : Comparable<T>, T : Any